package com.csjung.games.gamenori.server.service.impl;

import com.google.appengine.api.channel.ChannelMessage;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

import com.csjung.games.gamenori.server.MemcacheKey;
import com.csjung.games.gamenori.server.domain.GamenoriChannel;
import com.csjung.games.gamenori.server.domain.User;
import com.csjung.games.gamenori.server.service.GamenoriUserService;
import com.csjung.games.gamenori.shared.ChannelMsgs;

import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service("GamenoriUserService")
public class GamenoriUserServiceImpl implements GamenoriUserService {
  
  @Override
  public User getCurrentUser() {
    com.google.appengine.api.users.User currentUser = 
        UserServiceFactory.getUserService().getCurrentUser();
    ChannelService channelService = ChannelServiceFactory.getChannelService(); 
    MemcacheService mcs = MemcacheServiceFactory.getMemcacheService();
    User user = null;
    if (currentUser == null) {
      throw new RuntimeException("User not logged in");
    } else {
      Map<String, User> users = getMcsUsers();
      try {
        user = users.get(currentUser.getUserId());
        String token = channelService.createChannel(currentUser.getUserId());
        if (user == null) {
          // 캐시 유저
          user = new User();
          user.setUserId(currentUser.getUserId());
          user.setNickname(currentUser.getNickname());
          user.setChannelToken(token);
          //user.persist();
          users.put(currentUser.getUserId(), user);
        } else {
          user.setNickname(currentUser.getNickname());
          user.setChannelToken(token);
        }
        mcs.put(MemcacheKey.USERS_KEY, users);
        // 새로운 유저가 들어 온 것을 알림
        for (User obj : users.values()) {
          if (!obj.getUserId().equals(currentUser.getUserId())) {
            GamenoriChannel channel = new GamenoriChannel();
            channel.setCreateUserId(currentUser.getUserId());
            channel.setChannelType(ChannelMsgs.NEWUSER);
            channelService.sendMessage(new ChannelMessage(obj.getUserId(), channel.getJsonString()));  
          }
        }
          
      } catch (Exception e) {
        throw new RuntimeException(e.getMessage());
      }
    }
    return user;
  }

  @Override
  public User getUser(String userId) {
    Map<String, User> users = getMcsUsers();
    return users.get(userId);
  }

  @Override
  public String createLoginURL(String destinationURL) {
    return UserServiceFactory.getUserService().createLoginURL(destinationURL);
  }

  @Override
  public String createLogoutURL(String destinationURL) {
    UserService userService = UserServiceFactory.getUserService();
    String returnUrl = userService.createLogoutURL(destinationURL);
    return returnUrl;
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<User> getAllUsers() {
    MemcacheService mcs = MemcacheServiceFactory.getMemcacheService();
    Map<String, User> users = (Map<String, User>)mcs.get(MemcacheKey.USERS_KEY);
    if (users == null) {
      users = new HashMap<String, User>();
      mcs.put(MemcacheKey.USERS_KEY, users);
    }
    List<User> userList = new ArrayList<User>(users.values());
    com.google.appengine.api.users.User currentUser = 
        UserServiceFactory.getUserService().getCurrentUser();
    userList.remove(users.get(currentUser.getUserId()));
    return userList;
  }
  
  @Override
  public String notifyLogined(String userId) {
    Map<String, User> users = getMcsUsers();
    // 새로운 유저가 들어 온 것을 알림
    for (User obj : users.values()) {
      if (obj.getUserId().equals(userId)) {
        ChannelService channelService = ChannelServiceFactory.getChannelService(); 
        channelService.sendMessage(new ChannelMessage(obj.getUserId(), "open"));  
      }
    }
    return userId;
    
  }

  @Override
  @SuppressWarnings("unchecked")
  public void notifyLogout(String userId) {
    MemcacheService mcs = MemcacheServiceFactory.getMemcacheService();
    ChannelService channelService = ChannelServiceFactory.getChannelService(); 
    Map<String, User> users = (Map<String, User>)mcs.get(MemcacheKey.USERS_KEY);
    User user = users.remove(userId);
    if (user == null) {
      com.google.appengine.api.users.User currentUser = 
          UserServiceFactory.getUserService().getCurrentUser();
      user = users.remove(currentUser.getUserId());
    }
    
    // 유저가 나간다는 것을 알림
    for (User obj : users.values()) {
        GamenoriChannel channel = new GamenoriChannel();
        //channel.setToken(token);
        channel.setCreateUserId(obj.getUserId());
        channel.setChannelType(ChannelMsgs.LOGOUT);
        channelService.sendMessage(new ChannelMessage(obj.getUserId(), channel.getJsonString())); 
    }
    mcs.put(MemcacheKey.USERS_KEY, users);
  }

  @SuppressWarnings("unchecked")
  private Map<String, User> getMcsUsers() {
    MemcacheService mcs = MemcacheServiceFactory.getMemcacheService();
    Map<String, User> users = (Map<String, User>)mcs.get(MemcacheKey.USERS_KEY);
    if (users == null) {
      users = new HashMap<String, User>();
      mcs.put(MemcacheKey.USERS_KEY, users);
    }
    return users;
  }
}
